package com.util;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;


public class BaseDao {
    /*
   通用的增、删、改的方法
   String sql：sql
   Object... args：给sql中的?设置的值列表，可以是0~n
    */
    public int update(String sql, Object... args) throws Exception {
        //        创建PreparedStatement对象，对sql预编译
        Connection connection = JDBCTools.getConnection();
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //设置?的值
        if (args != null && args.length > 0) {
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i + 1, args[i]);//?的编号从1开始，不是从0开始，数组的下标是从0开始
            }
        }
        //执行sql
        int len = preparedStatement.executeUpdate();
        preparedStatement.close();
        //这里检查下是否开启事务,开启不关闭连接,业务方法关闭!
        //没有开启事务的话,直接回收关闭即可!
        if (connection.getAutoCommit()) {
            //回收
            JDBCTools.free();

        }
        return len;
    }

    /*
   通用的查询多个Javabean对象的方法，例如：多个员工对象，多个部门对象等
   这里的clazz接收的是T类型的Class对象，
   如果查询员工信息，clazz代表Employee.class，
   如果查询部门信息，clazz代表Department.class，
    */
    public static <T> ArrayList<T> query(Class<T> clazz, String sql, Object... args) throws Exception {
        //        创建PreparedStatement对象，对sql预编译
        Connection connection = JDBCTools.getConnection();
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //设置?的值
      /*  if (args.length > 0 && args != null) {
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i + 1, args[1]);
            }
        }*/
        if (args.length > 0 && args!= null) {
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i + 1, args[i]);
            }
        }
        //执行sql
        ResultSet resultSet = preparedStatement.executeQuery();


        ArrayList<T> arrayList = new ArrayList<>();
        ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
        int count = resultSetMetaData.getColumnCount();

        //遍历结果集ResultSet，把查询结果中的一条一条记录，变成一个一个T 对象，放到list中。
        while (resultSet.next()) {
            //循环一次代表有一行，代表有一个T对象
            T t = clazz.newInstance();//要求这个类型必须有公共的无参构造
            //把这条记录的每一个单元格的值取出来，设置到t对象对应的属性中。
            for (int i = 1; i <= count; i++) {
                //for循环一次，代表取某一行的1个单元格的值
                Object value = resultSet.getObject(i);
                //这个值应该是t对象的某个属性值
                //获取该属性对应的Field对象
                //这里再取别名可能没办法对应上
                String columnName = resultSetMetaData.getColumnLabel(i);//获取第i列的字段名或字段的别名
                Field field = clazz.getDeclaredField(columnName);
                field.setAccessible(true);//这么做可以操作private的属性
                field.set(t, value);
            }
            arrayList.add(t);
        }
        resultSet.close();
        preparedStatement.close();
        //这里检查下是否开启事务,开启不关闭连接,业务方法关闭!
        //没有开启事务的话,直接回收关闭即可!
        if (connection.getAutoCommit()) {
            //回收
            JDBCTools.free();
        }
        return arrayList;
    }
    /*public static <T> ArrayList<T> query(Class<T> clazz, String sql, Object... args) throws Exception {
        // 使用try-with-resources自动管理资源
        try (Connection connection = JDBCTools.getConnection();
             PreparedStatement preparedStatement = connection.prepareStatement(sql)) {

            // 设置?的值
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i + 1, args[i]); // 修复为args[i]
            }

            // 执行sql并处理结果集
            try (ResultSet resultSet = preparedStatement.executeQuery()) {
                ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
                int count = resultSetMetaData.getColumnCount();
                ArrayList<T> arrayList = new ArrayList<>();

                while (resultSet.next()) {
                    T t = clazz.newInstance(); // 要求有公共无参构造
                    for (int i = 1; i <= count; i++) {
                        Object value = resultSet.getObject(i);
                        String columnName = resultSetMetaData.getColumnLabel(i);
                        try {
                            Field field = clazz.getDeclaredField(columnName);
                            field.setAccessible(true);
                            field.set(t, value);
                        } catch (NoSuchFieldException e) {
                            // 处理字段不存在的情况，例如记录日志或跳过该字段
                            System.err.println("No field found for column: " + columnName);
                        }
                    }
                    arrayList.add(t);
                }
                return arrayList;
            }
        } finally {
            // 如果未开启事务，则关闭连接（JDBCTools.free()应负责关闭连接）

        }
    }*/

    public <T> T queryBean(Class<T> clazz, String sql, Object... args) throws Exception {
        ArrayList<T> arrayList = query(clazz,sql,args);
        if (arrayList == null  || arrayList.size() ==0){
            return null;
        }
        return arrayList.get(0);
    }

}
